import type Ts from 'typescript';
import { defineRule, type Reporter } from '@tsslint/config';
import { type Rule, type RuleContext } from '@tsslint/config';
interface PositionWithLine {
  node: Ts.ImportSpecifier;
  start: number;
  end: number;
  line: number;
}
type OneSpecifier = {
  [k: string]: PositionWithLine;
};
/// # Combinable: KindSpecial, OnceWalk, pre
/// Batch Fix

// 1. import 只能出现在顶层作用域
// 2. type 项的单个量只能出现在 NamedImports节点内
// 3. 最小的修复分块为单个 ImportDeclaration

// css选择器表示
// ImportDeclaration > ImportClause > NamedImports,
// ImportDeclaration > ImportClause > Identifier + NamedImports {}

function splitTypeImport(): Rule {
  return defineRule(
    ({
      typescript: ts,
      sourceFile,
      reportWarning,
      languageService: ls,
      languageServiceHost: lsh,
    }: RuleContext) => {
      const Warning_Title =
        'mixin type import and value import, prefer to split type import to new line';
      const Fix_Title = 'Split **ALL** type import to new line';

      ts.forEachChild(sourceFile, function cbImportDeclaration(node: Ts.Node) {
        if (ts.isImportDeclaration(node)) {
          // # ForEach ImportDeclaration
          const importDeclarationNode = node;

          // #region get importSourceSSring, importClauseNode
          //  getChildren
          const [importSource, importClause] = (() => {
            // ImportDeclaration > ImportClause + StringLiteral
            const importDeclarationNodeChildren =
              importDeclarationNode.getChildren();
            const importSource = importDeclarationNodeChildren.find((n) =>
              ts.isStringLiteral(n),
            );

            // ImportDeclaration > ImportClause (forEachChildren)
            const importClause = importDeclarationNodeChildren.find((n) =>
              ts.isImportClause(n),
            );
            return [importSource, importClause];
          })();
          
          if (!importSource || !importClause) {
            return;
          }
          // #endregion

          // #region walk to NamedImports
          // ImportClause > NamedImports (forEachChildren)
          // NamedImports 和 ImportClause 有时可以相等
          const namedImports = importClause
            .getChildren()
            .find((n: Ts.Node) => ts.isNamedImports(n));
          if (!namedImports) {
            return; /* OutTheRule */
          }
          // #endregion

          // #new Map<TypeSpecifier, PositionWithLine>
          // 使用Array,因为不可能有重复的key且顺序不重要
          const typeSpecifierSummery: OneSpecifier[] = [];
          ts.forEachChild(namedImports, function cbNamedImports(node: Ts.Node) {
            // should be true, only check
            if (ts.isImportSpecifier(node) && ts.isTypeNode(node)) {
              if (node.isTypeOnly) {
                typeSpecifierSummery.push({
                  [node.getText()]: {
                    node: node,
                    end: node.getEnd(),
                    start: node.getStart(),
                    line: ts.getLineAndCharacterOfPosition(
                      sourceFile,
                      namedImports.parent.getEnd(),
                    ).line,
                  },
                });
              }
              /// todo: 收集内容, 到最后一个时再触发 report
            }
          });
          for (const value of typeSpecifierSummery) {
            console.log(value);
            const madeFix: Ts.TextChange[] = [
              {
                // 1. gen type import 
                // should create new import once...
                newText: `\nimport type { ${node.getText().slice(5)} } from ${importSource.getText()};\n`,
                span: {
                  start: importDeclarationNode.getEnd(),
                  length: 1,
                },
              },
              // 2. remove old type specifier
              // 这里可能需要gen多次
              {
                newText: '',
                span: {
                  start: node.getStart(sourceFile),
                  // 附加如果结尾是换行,去除换行
                  length: node.getText().length + 1,
                },
              },
            ];
            reportWarning(
              Warning_Title + ',len:' + typeSpecifierSummery.length,
              node.getStart(sourceFile),
              node.getEnd(),
            )
              // once
              .withFix(Fix_Title, () => {
                // do collect type specifier
                return [
                  {
                    fileName: sourceFile.fileName,
                    textChanges: madeFix,
                  },
                ];
              });
          }
        }
        // 可能一直无法识别namespace的import
      });

      // out of forEachChild
    },
  );
}

export default splitTypeImport;
